var CountIntervals = function () {
  this.R = new RangeModule()
};

/** 
 * @param {number} left 
 * @param {number} right
 * @return {void}
 */
CountIntervals.prototype.add = function (left, right) {
  const r = this.R
  r.addRange(left, right + 1)
};

/**
 * @return {number}
 */
CountIntervals.prototype.count = function () {
  const r = this.R
  return Math.abs(r.ranges.reduce((pre,cur) => pre+cur, 0))
};

/**
 * Your CountIntervals object will be instantiated and called as such:
 * var obj = new CountIntervals()
 * obj.add(left,right)
 * var param_2 = obj.count()
 */

function isEven(val) {
  return val % 2 == 0;
}

function isOdd(val) {
  return !isEven(val);
}

var RangeModule = function () {
  this.ranges = [];
};

RangeModule.prototype.binarySearch = function (val) {
  let low = 0, high = this.ranges.length - 1;
  while (low <= high) {
    const mid = Math.trunc((high + low) / 2);
    const curValue = Math.abs(this.ranges[mid]);
    switch (true) {
      case val < curValue:
        high = mid - 1;
        break;
      case val > curValue:
        low = mid + 1;
        break;
      case val == curValue:
        return mid;
    }
  }
  return low;
}

RangeModule.prototype.addRange = function (left, right) {
  const startIndex = this.binarySearch(left);
  const endIndex = this.binarySearch(right);
  const insertNums = [];
  let spliceCount = endIndex - startIndex;
  if (isEven(startIndex)) {
    insertNums.push(left);
  }
  if (isEven(endIndex)) {
    if (endIndex < this.ranges.length && right == this.ranges[endIndex]) {
      spliceCount++;
    }
    else {
      insertNums.push(-right);
    }
  }
  this.ranges.splice(startIndex, spliceCount, ...insertNums);
};

RangeModule.prototype.queryRange = function (left, right) {
  const startIndex = this.binarySearch(left);
  const endIndex = this.binarySearch(right);
  if (startIndex < this.ranges.length) {
    if (isEven(startIndex)) {
      if (left == this.ranges[startIndex]) {
        return startIndex + 1 == endIndex;
      }
    }
    else {
      if (left < Math.abs(this.ranges[startIndex])) {
        return startIndex == endIndex;
      }
    }
  }
  return false;
};

RangeModule.prototype.removeRange = function (left, right) {
  const startIndex = this.binarySearch(left);
  const endIndex = this.binarySearch(right);
  const insertNums = [];
  let spliceCount = endIndex - startIndex;
  if (isOdd(startIndex)) {
    insertNums.push(-left);
  }
  if (isOdd(endIndex)) {
    if (right == Math.abs(this.ranges[endIndex])) {
      spliceCount++;
    }
    else {
      insertNums.push(right);
    }
  }
  this.ranges.splice(startIndex, spliceCount, ...insertNums);
};